package com.study.pugdogcommon.aop.log;

import com.alibaba.fastjson.JSON;
import com.study.pugdogcommon.annotation.log.Log;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @Author suxiaoxiao
 * @Date 2019/5/17 1:39
 * @Version 1.0
 */
@Aspect
@Slf4j
@Component("logAspect")
public class LogAspect {

    /**
     * 切点
     */
    @Pointcut("@annotation(com.study.pugdogcommon.annotation.log.Log)")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object handle(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获得类名
        String className = joinPoint.getTarget().getClass().getName();
        // 获得方法名
        String methodName = joinPoint.getSignature().getName();
        // 方法耗时
        long startTime = System.currentTimeMillis();
        // 获取注解中的描述信息字段
        String description = getAspectLogDescription(joinPoint);
        // 入参
        log.info("|| class : [{}], method : [{}], description : [{}], requestParam : [{}]",
                className, methodName, description, JSON.toJSON(joinPoint.getArgs()));
        Object result= joinPoint.proceed();
        // 出参
        log.info("|| class : [{}], method : [{}], responseParam : [{}], time-consuming : {} ms",
                className, methodName, postHandle(result), System.currentTimeMillis() - startTime);
        return result;
    }

    /**
     * 返回数据
     * @param retVal
     * @return
     */
    private String postHandle(Object retVal) {
        if(null == retVal){
            return "";
        }
        return JSON.toJSONString(retVal);
    }

    /**
     * 获取切面注解的描述
     *
     * @param joinPoint 切点
     * @return 描述信息
     * @throws Exception
     */
    public String getAspectLogDescription(JoinPoint joinPoint)
            throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        StringBuilder description = new StringBuilder("");
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description.append(method.getAnnotation(Log.class).description());
                    break;
                }
            }
        }
        return description.toString();
    }

}
